package quicklunch.e1.goodies.utils;

import static quicklunch.e1.goodies.utils.StringUtils.hasLength;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.jxpath.JXPathContext;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

public abstract class JXPathUtils {

    public static JXPathContext createJXPathContext(URL url) throws JXPathUtilsRuntimeException {
        File file;
        try {
            file = FileUtils.toFile(url);
            return createJXPathContext(file);
        } catch (FileNotFoundException e) {
            throw new JXPathUtilsRuntimeException(e);
        } catch (ParserConfigurationException e) {
            throw new JXPathUtilsRuntimeException(e);
        } catch (FactoryConfigurationError e) {
            throw new JXPathUtilsRuntimeException(e);
        } catch (SAXException e) {
            throw new JXPathUtilsRuntimeException(e);
        } catch (IOException e) {
            throw new JXPathUtilsRuntimeException(e);
        }
    }

    public static JXPathContext createJXPathContext(byte[] b) throws ParserConfigurationException,
            FactoryConfigurationError, SAXException, IOException {
        DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        Document document = builder.parse(new ByteArrayInputStream(b));
        JXPathContext pathContext = JXPathContext.newContext(document);
        return pathContext;
    }

    public static JXPathContext createJXPathContext(File file) throws ParserConfigurationException,
            FactoryConfigurationError, SAXException, IOException {
        DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        Document document = builder.parse(file);
        JXPathContext pathContext = JXPathContext.newContext(document);
        return pathContext;
    }

    public static int count(JXPathContext pathContext, String s) {

        Object countVal = pathContext.getValue("count(" + s + ")");

        if (countVal instanceof Integer) {
            return ((Integer) countVal).intValue();
        } else if (countVal instanceof Double) {
            return ((Double) countVal).intValue();
        }

        return 0;
    }

    public static String getValueAsString(JXPathContext pathContext, String path,
            String defaultValue) {
        try {
            return getValueAsString(pathContext, path);
        } catch (JXPathUtilsRuntimeException e) {

        }
        return defaultValue;
    }

    public static String getValueAsString(JXPathContext pathContext, String path)
            throws JXPathUtilsRuntimeException {

            Object object = pathContext.getValue(path);
           
            return object != null ?object.toString():null;
        

    }

    public static Element getElement(JXPathContext pathContext, String path)
            throws JXPathUtilsRuntimeException {
        try {
            Object object = pathContext.selectSingleNode(path);
            if (object instanceof Element) {
                Element element = (Element) object;
                return element;
            }
            return null;
        } catch (org.apache.commons.jxpath.JXPathException e) {
            throw new JXPathUtilsRuntimeException(e);
        }

    }

    public static int getValueAsint(JXPathContext pathContext, String path, int defaultValue) {

        try {
            Object object = pathContext.getValue(path);
            String s = object.toString();
            return new Integer(s).intValue();
        } catch (Exception e) {
        }
        return defaultValue;
    }

    public static boolean getValueAsboolean(JXPathContext pathContext, String path,
            boolean defaultValue) {

        try {
            Object object = pathContext.getValue(path);
            Boolean boolean1 = new Boolean(object.toString());
            return boolean1.booleanValue();
        } catch (Exception e) {
        }
        return defaultValue;
    }

    public static String getElementAsString(JXPathContext pathContext, String path) {
        return DOMUtils.toString(getElement(pathContext, path));
    }

    public static String getElementAsString(JXPathContext pathContext, String path,
            String defaultValue) {
        String s = null;
        try {
            s = getElementAsString(pathContext, path);
        } catch (Exception e) {

        }
        if (!hasLength(s))
            return defaultValue;
        return s;
    }

    public static void setValue(JXPathContext pathContext, String xpath, String string) {
        pathContext.setValue(xpath, string);
    }

    static class JXPathUtilsRuntimeException extends RuntimeException {

        private static final long serialVersionUID = 1L;

        public JXPathUtilsRuntimeException() {
            super();
        }

        public JXPathUtilsRuntimeException(String message, Throwable cause) {
            super(message, cause);
        }

        public JXPathUtilsRuntimeException(String message) {
            super(message);
        }

        public JXPathUtilsRuntimeException(Throwable cause) {
            super(cause);
        }

    }

}
